import h5py
import random
import pickle
import scipy.io
import numpy as np
import pandas as pd
import matplotlib.image
import statsmodels.api as sm
import matplotlib.pyplot as plt
from scipy.signal import savgol_filter


lowess = sm.nonparametric.lowess
csvData = pd.read_csv('F:\PycharmProjects\ML&DL\kneepoint\Batch3KneePoint.csv', header=None)  # header=None是去掉表头部分
csvData = csvData.iloc[:, 0]
allKneePoint = np.array(csvData).astype(int)


def LoadQandV(filename):
    f = h5py.File(filename)
    list(f.keys())
    batch = f['batch']
    list(batch.keys())
    # num_cells = batch['summary'].shape[0]
    for o in range(0, 45):
        cycles = f[batch['cycles'][o, 0]]
        # 一个电池的数据
        one_battery_QITV = []
        # 先取第1个数据
        t_to_q = []
        t_to_i = []
        t_to_t = []
        t_to_v = []
        v_to_qd = []
        v_to_qc = []
        ts = []
        Q = []
        # ic曲线
        qdic = []
        qcic = []
        kneePoint = allKneePoint[o]

        # 获取距离膝点超过或少于100的周期的数据
        # 随机获取膝点前的某个循环的数据
        r = random.random()
        if r >= 0.5:
            if kneePoint - 150 > 0:
                cycle = random.randint(20, kneePoint - 150)
            else:
                cycle = random.randint(kneePoint - 70, kneePoint)
        if r < 0.5:
            cycle = random.randint(kneePoint - 70, kneePoint)
        print('r:' + str(r))
        print('cycle:' + str(cycle))
        print('kneepoint:' + str(kneePoint))
        for i in range(cycle - 2, cycle + 1):
            print(i)
            # Qd放电容量
            Qd = np.hstack((f[cycles['Qd'][i, 0]][()]))
            I = np.hstack((f[cycles['I'][i, 0]][()]))
            # print("I: ", I)
            T = np.hstack((f[cycles['T'][i, 0]][()]))
            V = np.hstack((f[cycles['V'][i, 0]][()]))
            # 时间
            t = np.hstack((f[cycles['t'][i, 0]][()]))
            # print("t: ", t)
            print("lenT: ", len(t), "lenI: ", len(I))
            # Qc充电容量
            Qc = np.hstack((f[cycles['Qc'][i, 0]][()]))

            # 计算Q曲线
            for j in range(0, len(Qd) - 1):
                if Qd[j] != 0:
                    Q = np.hstack([np.transpose(Qc[0:i - 1, np.newaxis]), 1.1 - np.transpose(Qd[i:-1, np.newaxis])])
                    break

            # 过滤出放电数据
            for j in range(0, Qd.shape[0] - 1):
                if Qd[j] > 0.00001:
                    Qd = Qd[j - 1:]
                    Qdv = V[j - 1:]
                    break

            # 过滤出充电数据
            idz = (np.abs(1.1 - Qc)).argmin()
            # 新的Qc为原Qc截取前idz个数据
            Qc = Qc[0:idz]
            # Qcv为原V截取前idz个数据
            # （Qcv代表什么意思？）
            Qcv = V[0:idz]

            # 取出600个充电放电点
            # 有关电压
            for k in range(0, 600):
                v_need = 2.0 + 0.0025 * k
                # Qdv是V里面的数据
                # np.argmin() 获取水平方向最小值的下标索引
                # （减去v_need的含义是什么？）
                Qdid = (np.abs(Qdv - v_need)).argmin()
                # 添加到v_to_qd中，索引值为上一步获取的最小索引
                v_to_qd.append(Qd[Qdid])
                # Qcv为原V截取前idz个数据
                Qcid = (np.abs(Qcv - v_need)).argmin()
                v_to_qc.append(Qc[Qcid])
            # 有关时间
            for k in range(0, 600):
                # 最后一位
                t_max = t[-1]
                # 第一位
                t_min = t[0]
                # （最大-最小）/600
                tdev = (t_max - t_min) / 600
                # print("tdev: ", tdev)
                t_need = t[0] + tdev * k
                # print("t_need: ", t_need)
                # 获取水平最小**的索引
                idx = (np.abs(t - t_need)).argmin()
                print("idx: ", idx)
                # t_to_q.append(Q[0,idx])
                # 分别把I V T t所对应idx索引的值添加到t_to_i， t_to_v， t_to_t， ts中
                t_to_i.append(I[idx])
                t_to_t.append(T[idx])
                t_to_v.append(V[idx])
                ts.append(t[idx])
                print("lents: ", len(ts), ", lent_to_i: ", len(t_to_i))
            print("************************************")
            print("************有关时间600结束***********")
            print("************************************")
            # v_to_qc=scipy.signal.savgol_filter(v_to_qc, 53, 5, mode='nearest')
            for p in range(0, 600):
                if p == 0:
                    qdic.append(0)
                    qcic.append(0)
                else:
                    if (v_to_qd[p - 1] - v_to_qd[p]) / 0.0025 < 0:
                        qdic.append(0)
                        qcic.append(0)
                    else:
                        qdic.append((v_to_qd[p - 1] - v_to_qd[p]) / 0.0025)
                        qcic.append((v_to_qc[p - 1] - v_to_qc[p]) / 0.0025)
            # one_battery_QITV.append(ic)
            '''plt.plot(ts,t_to_q)
            plt.ylabel('Q/(A·h)')
            plt.xlabel('Time/(Min)')
            plt.grid()
            plt.savefig('image/morethan100/q/' + str(o+94) + '_q.png')
            plt.clf()
            plt.cla()
            # plt.show()'''
        print("************************************")
        print("*************range45结束*************")
        print("************************************")
        one_battery_QITV.append(t_to_v)
        one_battery_QITV.append(t_to_i)
        one_battery_QITV.append(t_to_t)
        one_battery_QITV.append(qdic)
        x = np.linspace(2.0, 3.5, 600)
        # sm.nonparametric.lowess
        qdic[0:600] = lowess(qdic[0:600], x, frac=1. / 3.)[:, 1]
        qdic[600:1200] = lowess(qdic[600:1200], x, frac=1. / 3.)[:, 1]
        qdic[1200:1800] = lowess(qdic[1200:1800], x, frac=1. / 3.)[:, 1]
        qcic[0:600] = lowess(qcic[0:600], x, frac=1. / 3.)[:, 1]
        qcic[600:1200] = lowess(qcic[600:1200], x, frac=1. / 3.)[:, 1]
        qcic[1200:1800] = lowess(qcic[1200:1800], x, frac=1. / 3.)[:, 1]
        '''
        plt.subplot(1, 3, 1)
        plt.plot(x, qdic[0:600])
        plt.ylabel('dQ/dU/(A·h/V)')
        plt.xlabel('U/(V)')
        plt.grid()

        plt.subplot(1, 3, 2)
        plt.plot(x, qdic[600:1200])
        plt.ylabel('dQ/dU/(A·h/V)')
        plt.xlabel('U/(V)')
        plt.grid()

        plt.subplot(1, 3, 3)
        plt.plot(x, qdic[1200:1800])
        plt.ylabel('dQ/dU/(A·h/V)')
        plt.xlabel('U/(V)')
        plt.grid()

        plt.savefig('image/qdic/' + str(o + 140) + '_qdic.png')
        plt.clf()
        plt.cla()
        # plt.show()

        plt.plot(v_to_qc, qcic)
        plt.subplot(1, 3, 1)
        plt.plot(x, qcic[0:600])
        plt.ylabel('dQ/dU/(A·h/V)')
        plt.xlabel('U/(V)')
        plt.grid()

        plt.subplot(1, 3, 2)
        plt.plot(x, qcic[600:1200])
        plt.ylabel('dQ/dU/(A·h/V)')
        plt.xlabel('U/(V)')
        plt.grid()

        plt.subplot(1, 3, 3)
        plt.plot(x, qcic[1200:1800])
        plt.ylabel('dQ/dU/(A·h/V)')
        plt.xlabel('U/(V)')
        plt.grid()
        # 保存
        plt.savefig('image/qcic/' + str(o + 140) + '_qcic.png')
        plt.clf()
        plt.cla()
        # plt.show()

        # t_to_i=savgol_filter(t_to_i, 5, 3, mode= 'nearest')
        '''
        print(ts[0:600])
        print(t_to_i[0:600])
        # plt.subplot(1, 3, 1)
        plt.plot(ts[0:600], t_to_i[0:600])
        plt.ylabel('I/(A)')
        plt.xlabel('Time/(Min)')
        plt.grid()
        plt.show()

        # plt.subplot(1, 3, 2)
        # plt.plot(ts[600:1200], t_to_i[600:1200])
        # plt.ylabel('I/(A)')
        # plt.xlabel('Time/(Min)')
        # plt.grid()

        # plt.subplot(1, 3, 3)
        # plt.plot(ts[1200:1800], t_to_i[1200:1800])
        # plt.ylabel('I/(A)')
        # plt.xlabel('Time/(Min)')
        # plt.grid()
        # plt.savefig('image/i/' + str(o + 140) + '_id.png')
        # plt.clf()
        # plt.cla()
        # plt.show()
        '''
        t_to_t = savgol_filter(t_to_t, 5, 3, mode='nearest')

        plt.subplot(1, 3, 1)
        plt.plot(ts[0:600], t_to_t[0:600])
        plt.ylabel('T/(℃)')
        plt.xlabel('Time/(Min)')
        plt.grid()

        plt.subplot(1, 3, 2)
        plt.plot(ts[600:1200], t_to_t[600:1200])
        plt.ylabel('T/(℃)')
        plt.xlabel('Time/(Min)')
        plt.grid()

        plt.subplot(1, 3, 3)
        plt.plot(ts[1200:1800], t_to_t[1200:1800])
        plt.ylabel('T/(℃)')
        plt.xlabel('Time/(Min)')
        plt.grid()
        plt.savefig('image/t/' + str(o + 140) + '_td.png')
        plt.clf()
        plt.cla()
        # plt.show()

        t_to_v = savgol_filter(t_to_v, 5, 3, mode='nearest')

        plt.subplot(1, 3, 1)
        plt.plot(ts[0:600], t_to_v[0:600])
        plt.ylabel('U/(V)')
        plt.xlabel('Time/(Min)')
        plt.grid()

        plt.subplot(1, 3, 2)
        plt.plot(ts[600:1200], t_to_v[600:1200])
        plt.ylabel('U/(V)')
        plt.xlabel('Time/(Min)')
        plt.grid()

        plt.subplot(1, 3, 3)
        plt.plot(ts[1200:1800], t_to_v[1200:1800])
        plt.ylabel('U/(V)')
        plt.xlabel('Time/(Min)')
        plt.grid()
        plt.savefig('image/v/' + str(o + 140) + '_vd.png')
        plt.clf()
        plt.cla()
        # plt.show()
        '''

        '''
        one_battery_QITV = np.array(one_battery_QITV).reshape(4, 1800)
        np.savetxt('data/' + str(o + 140) + ".txt", one_battery_QITV, fmt='%f', delimiter=',')
        result = np.array([cycle, kneePoint])
        np.savetxt('csv/' + str(o + 140) + '.csv', result, delimiter=',')
        # im = Image.fromarray(one_battery_V)
        # im = im.convert('L')  # 这样才能转为灰度图，如果是彩色图则改L为‘RGB’
        # im.save('graypicture/'+str(o)+'.jpg')
        # matplotlib.image.imsave('picture/'+str(o)+'.jpg', one_battery_V)
        '''

LoadQandV('2019-01-24_batchdata_updated_struct_errorcorrect.mat')
